<template>
  <plain-page
    v-loading="loading"
    element-loading-text="查询中"
    element-loading-background="transparent"
    :style="{backgroundColor: colorThemeData.backgroundColor}"
  >
    <wake-up
      v-show="!loading"
      v-model="optionsVisible"
      :on-event="['mousemove', 'click']"
      :active-duration="2000"
      :class="['options', {hide: !optionsVisible}]"
    >
      <el-form inline size="mini">
        <el-form-item label="图表类型">
          <radio-options
            v-model="chartType"
            :options="chartTypes"
            valueField="name"
            textField="title"
          />
        </el-form-item>
        <el-form-item label="排序">
          <radio-options
            v-model="sortType"
            :options="[{text: '按计数', value: 'count'}, {text: '按字典', value: 'dict'}]"
          />
        </el-form-item>
        <el-form-item label="颜色" class="color-picker-form-item">
          <type-select
            v-model="colorTheme"
            :items="[
              {text: '浅色', value: 'light'},
              {text: '深色', value: 'dark'},
              {text: '朴素', value: 'plain'},
              {text: '自定', value: 'custom'}
            ]"
            :clearable="false"
            style="width: 72px"
            @click.native="onColorPickerClick"
          />
        </el-form-item>
        <el-form-item label="背景" class="color-picker-form-item" @click.native="onColorPickerClick">
          <el-color-picker v-model="colorThemeData.backgroundColor" :disabled="colorTheme != 'custom'" show-alpha />
        </el-form-item>
        <el-form-item label="图表" class="color-picker-form-item" @click.native="onColorPickerClick">
          <el-color-picker v-model="colorThemeData.chartCardColor" :disabled="colorTheme != 'custom'"  show-alpha />
        </el-form-item>
        <el-form-item label="字体" class="color-picker-form-item" @click.native="onColorPickerClick">
          <el-color-picker v-model="colorThemeData.textColor" :disabled="colorTheme != 'custom'"  show-alpha	/>
        </el-form-item>
        <el-form-item label="每行图数">
          <el-input-number v-model="chartsInRow" controls-position="right" :min="1" style="width: 74px"	/>
        </el-form-item>
        <el-form-item class="icon-buttons">
          <el-tooltip content="网页全屏">
            <el-button plain icon="el-icon-data-board" @click="onFullScreenClick(1)" />
          </el-tooltip>
          <el-tooltip content="全屏">
            <el-button plain icon="el-icon-full-screen" @click="onFullScreenClick(2)" />
          </el-tooltip>
        </el-form-item>
      </el-form>
    </wake-up>
    <div ref="chartsContainer" class="charts">
      <el-card
        v-for="(chartData, major) in chartDataMap"
        :key="major"
        shadow="never"
        class="chart-card"
        :style="{
          backgroundColor: colorThemeData.chartCardColor,
          width: chartWidth,
          height: '390px'
        }"
      >
        <span slot="header" :style="{color: colorThemeData.textColor}">{{chartData.title}}</span>
        <component
          :ref="`chartOf${major}`"
          :is="chartTypeComponent"
          :data="chartData"
          :grid="{top: 0, height: 'auto'}"
          :title="computedTitle(chartData)"
          :legend="{
            show: !['VeBar', 'VeHistogram'].includes(chartType),
            textStyle: {color: colorThemeData.textColor}
          }"
          :text-style="{color: colorThemeData.textColor}"
          :extend="['VePie', 'VeRing', 'VeFunnel'].includes(chartType)
            ? (chartOptionsMap[major] && chartOptionsMap[major].extend)
            : null"
        />
      </el-card>
    </div>
  </plain-page>
</template>

<script>
import { majorTitleMap } from './dicts';
import RadioOptions from '@/components/RadioOptions';
import WakeUp from '@/components/WakeUp';
import fullScreen, { isFullScreen } from '@/utils/fullscreen';
import VePie from 'v-charts/lib/pie.common';
import VeHistogram from 'v-charts/lib/histogram.common';
import VeRing from 'v-charts/lib/ring.common';
import VeFunnel from 'v-charts/lib/funnel.common';
import VeBar from 'v-charts/lib/bar.common';

export default {
  pageProps: {
    title: '用户数据统计'
  },
  components: {
    RadioOptions,
    WakeUp
  },
  data() {
    this.chartTypes = [
      {component: VePie, title: '饼图'},
      {component: VeRing, title: '环图'},
      {component: VeBar, title: '条形图'},
      {component: VeHistogram, title: '柱形图'},
      {component: VeFunnel, title: '漏斗图'}
    ].map(item => ({...item, name: item.component.name}));

    this.chartOptionsMap = {
      homeCareNeeds: {
        extend: {
          series: {label: {show: false}}
        }
      },
      specialTypes: {
        extend: {
          series: {label: {show: false}}
        }
      },
      disease: {
        extend: {
          series: {label: {show: false}}
        }
      }
    };
    
    this.presetColorThemeData = {
      light: {
        backgroundColor: '#EBEEF5',
        chartCardColor: '#f0f2f5',
        textColor: '#303133'
      },
      dark: {
        backgroundColor: '#000',
        chartCardColor: '#111',
        textColor: '#fff'
      },
      plain: {
        backgroundColor: '#f0f2f5',
        chartCardColor: '#f0f2f5',
        textColor: '#303133'
      }
    };

    return {
      loading: true,
      optionsVisible: false,
      sortType: null,
      pageWidth: 0,
      colorTheme: 'light',
      colorThemeData: {
        backgroundColor: null,
        chartCardColor: null,
        textColor: null
      },
      chartsInRow: 3,
      chartType: VePie.name,
      chartTypeComponent: VePie,
      chartDataMap: {}
    };
  },
  computed: {
    chartWidth() {
      return ((this.pageWidth - (this.chartsInRow + 1) * 4) / this.chartsInRow) + 'px';
    }
  },
  watch: {
    chartType(type) {
      this.chartTypeComponent = this.chartTypes.find(t => t.name == type).component;
    },
    colorTheme: {
      handler(themeName) {
        if (themeName != 'custom') {
          this.colorThemeData = {...this.presetColorThemeData[themeName]};
        } else {
          this.colorThemeData = {...this.presetColorThemeData['plain']};
        }
      },
      immediate: true
    },
    chartsInRow(num) {
      if (num > 2) {
        setTimeout(() => {
          for (let ref in this.$refs) {
            if (ref.startsWith('chartOf')) {
              this.$refs[ref][0].echarts.resize();
            }
          }
        }, 500);
      }
    },
    sortType(type) {
      for (let major in this.chartDataMap) {
        let charData = this.chartDataMap[major];
        let rows;
        switch (type) {
          case 'count':
            rows = [...charData.dictOrderRows];
            rows.sort((a, b) => b['数量'] - a['数量']);
            break;
          case 'dict':
            rows = charData.dictOrderRows;
            break;
        }
        charData.rows = rows;
      }
    },
    optionsVisible(visible) {
      if (visible) {
        if (this.scrollbarWidth && isFullScreen()) {
          this.pageWidth = this.pageWidth - this.scrollbarWidth;
        }
        setTimeout(() => {
          this.$el.parentNode.classList.remove('scrollbar--hide');
          setTimeout(() => {
            this.pageWidth = this.$el.offsetWidth;
          }, 0);
        }, this.scrollbarWidth && isFullScreen() ? 500 : 0);
      }  else {
        this.$el.parentNode.classList.add('scrollbar--hide');
        setTimeout(() => {
          this.scrollbarWidth = this.$el.offsetWidth - this.pageWidth;
          this.pageWidth = this.$el.offsetWidth;
        }, 0);
      }
    }
  },
  async mounted() {
    this.pageWidth = this.$el.offsetWidth;
    const onResize = () => {
      this.pageWidth = this.$el.offsetWidth;
      if (isFullScreen()) {
        this.$el.classList.add('full-screen');
      } else {
        this.$el.classList.remove('full-screen');
      }
    };
    window.addEventListener('resize', onResize);
    app.$refs.navMenu.$on('collapse-change', onResize);
    this.$once('hook:beforeDestroy', () => {
      window.removeEventListener('resize', onResize);
      app.$refs.navMenu && app.$refs.navMenu.$off('collapse-change', onResize);
    });
    this.loading = true;
    let ret = await this.$http.get('/api/user/stat', {params: this.$params.query, timeout: 15000});
    let { total, itemsMap, majorDictMap } = ret;

    this.total = total;

    let chartDataMap = {};
    for (let major in majorTitleMap) {
      if (!itemsMap[major]) continue;

      let rows = [];
      let count = 0;
      DictMan.items(majorDictMap[major]).forEach(({text: minorText, value: minorKey}) => {
        let cnt = itemsMap[major][minorKey] || 0;
        let row = {'类型': minorText, '数量': cnt};
        rows.push(row);
        count += cnt;
      });
      let charData = {
        title: majorTitleMap[major],
        columns: ['类型', '数量'],
        total: count,
        dictOrderRows: [...rows],
        rows
      };
      chartDataMap[major] = charData;
    }

    this.chartDataMap = chartDataMap;
    this.sortType = 'count';
    this.optionsVisible = true;
    this.loading = false;

    this.$nextTick(() => {
      this.$el.style.height = '100%';
    });
  },
  methods: {
    onFullScreenClick(type) {
      if (type == 1) {
        app.$refs.navMenu.switchCollapse();
      } else {
        fullScreen.switch(this.$el.parentNode);
      }
    },
    onColorPickerClick() {
      if (isFullScreen()) {
        fullScreen.switch(this.$el.parentNode);
        this.$alert('全屏状态下无法设置颜色。请先退出全屏之后，再进行设置，设置好之后，再进入全屏。');
      }
    },
    computedTitle(chartData) {
      if (!['VePie', 'VeRing'].includes(this.chartType)) return {};
      let text = chartData.total;
      if (chartData.total < this.total) {
        text += ` (${(chartData.total / this.total * 100).toFixed(2)}%)`;
      }
      return {
        text,
        x: 'center',
        y: 'center',
        itemGap:20,
        textStyle : {
          color: this.chartType == 'VePie' ? '#fafafa' : this.colorThemeData.textColor,
          fontSize : 14,
          fontWeight: 'normal'
        }
      };
    }
  },
}
</script>

<style scoped>
.plain-page {
  border-radius: 4px;
   /* 让它一开始就出现滚动条，使得图表宽度是基于减去滚动条宽度计算的 */
  height: calc(100% + 1px);
  min-height: unset !important;
}
.plain-page.full-screen {
  border-radius: 0px;
}

.options {
  display: flex;
  justify-content: flex-end;
  margin-right: 20px;
  padding: 0px 4px 0px 12px;
  position: fixed;
  right: 0px;
  z-index: 1;
  opacity: 1;
  transition: .3s opacity ease-in-out;
  background-color: rgba(0, 0, 0, 0.5);
  border-radius: 4px;
}
.options.hide {
  opacity: 0;
}
.options .el-form > .el-form-item {
  margin-bottom: 0px;
  vertical-align: middle;
}
.options .el-form > .el-form-item >>> .el-form-item__label,
.options .el-form > .el-form-item >>> .el-radio__label {
  color: #fafafa;
}
.options .el-form > .el-form-item.color-picker-form-item >>> .el-form-item__label {
  padding-right: 4px;
  line-height: 37px;
}
.options .el-form > .el-form-item >>> .el-select {
  line-height: 37px;
}
.options .el-form > .el-form-item.color-picker-form-item >>> .el-color-picker {
  top: 5px;
}
.options .icon-buttons .el-button {
  width: 30px;
  padding-left: 0px;
  padding-right: 0px;
}

.charts {
  display: flex;
  flex-wrap: wrap;
  position: relative;
  padding: 2px;
}

.chart-card {
  margin: 2px;
  background: transparent;
  border: none;
}
.chart-card >>> .el-card__header {
  padding: 6px 0px 0px 0px;
  text-align: center;
  font-weight: bold;
  border-bottom: none;
}
.chart-card >>> .el-card__body {
  padding: 4px 0px 0px 0px;
  width: 100%;
}
.chart-card >>> .el-card__body > div > div > div {
  margin: 0 auto !important;
}
</style>
<style>
.scrollbar--hide.el-tab-pane::-webkit-scrollbar {
  display: none;
}
</style>